﻿using System.Linq;
using CardPlay.Model.ActionModel;
using CardPlay.Model.CardModel;
using CardPlay.Model.GameModel;
using CardPlay.Model.GameModel.Actions;

namespace CardPlay.DemoPack.Games.SirTommyVariants
{
    [Game("33FCF121-1B82-424A-893F-5027637F9A13", LevelOfDifficulty.Easy, LevelOfSkill.ChanceOnly, DurationOfPlay.LessThan5Minutes, Family = FamilyName)]
    public class Shuttle : SirTommy
    {
        private bool _shuttlingRightToLeft;

        public Shuttle()
        {
            MaximumDeals = null;
            TotalTableaus = 8;
        }

        protected override bool IsOver
        {
            get { return this.NonEmptyPilesNamed(AnyTableau).Count() == 1 && !PlaysAvailable; }
        }

        protected override void PrepareDealScript(DealScript script)
        {
            script.DealAcesTo(NamesOfFoundations);
            script.DealToEach(NamesOfTableaus, "6 up");
            script.DealRemainingFaceUpTo(Stock);
        }

        protected override IAction QueryActionAt(PartLocation location)
        {
            return location.Matches(Stock)
                ? CreateShuffleAction() 
                //? (PlaysAvailable ? null : CreateShuffleAction())
                : base.QueryActionAt(location);
        }

        protected override bool AllowedToBuildEmptyTableau(MovePileAction action)
        {
            return false;
        }

        protected override bool AllowedToBuildNonEmptyTableau(MovePileAction action)
        {
            return false;
        }

        private IAction CreateShuffleAction()
        {
            var series = (_shuttlingRightToLeft ? this.NonEmptyPilesNamed(AnyTableau).Reverse() : this.NonEmptyPilesNamed(AnyTableau)).ToArray();
            if (series.Length < 2) return null;
            
            var action = new ComplexAction
            {
                new DelegatingAction { OnExecute = SwitchShuttleDirection, OnReverse = SwitchShuttleDirection, }
            };

            for (var i = 1; i < series.Length; ++i)
            {
                var fromPile = series[i - 1];
                action.Add(new MoveCardAction(this, i == 1 ? fromPile.Top : new PartLocation(fromPile.Name, fromPile.Count), series[i].Bottom));
            }

            return action;
        }

        private void SwitchShuttleDirection()
        {
            _shuttlingRightToLeft = !_shuttlingRightToLeft;
        }

        private bool PlaysAvailable
        {
            get
            {
                var foundationTops = PilesNamed(AnyFoundation).Where(pile => pile.Count < CardFace.RanksPerSuit).Select(pile => new PartLocation(pile.Name, pile.Count));
                return this.NonEmptyPilesNamed(AnyTableau).Any(source => foundationTops.Any(target => Regulations.Permit(new MovePileAction(this, source.Top, target))));
            }
        }
    }
}